<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mincore函数深度解析 - 内存陷阱检测技术</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        :root {
            --primary: #4a6cfa;
            --secondary: #7e68ff;
            --accent: #ff6b6b;
            --success: #41d695;
            --warning: #ffc107;
            --dark: #2c3e50;
            --light: #f8f9fa;
            --card-bg: #ffffff;
            --header-height: 80px;
            --transition: all 0.3s ease;
        }
        
        body {
            background: linear-gradient(135deg, #f0f4ff, #e6f0ff);
            color: var(--dark);
            line-height: 1.7;
            min-height: 100vh;
            overflow-x: hidden;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 20px;
        }
        
        header {
            background: linear-gradient(to right, #2c3e50, #1a2530);
            color: white;
            padding: 1.5rem 0;
            box-shadow: 0 5px 25px rgba(0, 0, 0, 0.2);
            position: sticky;
            top: 0;
            z-index: 1000;
        }
        
        .header-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .logo {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .logo-icon {
            background: var(--primary);
            width: 50px;
            height: 50px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 22px;
            box-shadow: 0 0 20px rgba(74, 108, 250, 0.6);
        }
        
        .logo-text {
            font-size: 1.8rem;
            font-weight: 700;
            background: linear-gradient(to right, #4a6cfa, #7e68ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        nav ul {
            display: flex;
            list-style: none;
            gap: 30px;
        }
        
        nav a {
            color: rgba(255, 255, 255, 0.85);
            text-decoration: none;
            font-weight: 600;
            font-size: 1.1rem;
            padding: 8px 12px;
            border-radius: 8px;
            transition: var(--transition);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        nav a:hover, nav a.active {
            background-color: rgba(74, 108, 250, 0.3);
            color: white;
        }
        
        main {
            padding: 40px 0;
        }
        
        .section {
            background: white;
            border-radius: 16px;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
            margin-bottom: 40px;
            overflow: hidden;
            transform: translateY(0);
            transition: transform 0.4s ease, box-shadow 0.4s ease;
        }
        
        .section:hover {
            transform: translateY(-10px);
            box-shadow: 0 15px 50px rgba(0, 0, 0, 0.15);
        }
        
        .section-header {
            background: linear-gradient(to right, var(--primary), var(--secondary));
            color: white;
            padding: 25px 30px;
        }
        
        .section-title {
            font-size: 1.8rem;
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .section-content {
            padding: 30px;
        }
        
        .subsection {
            margin-bottom: 35px;
        }
        
        .subsection-title {
            font-size: 1.4rem;
            color: var(--primary);
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #f0f4ff;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .demo-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: 40px 0;
        }
        
        .demo-header {
            text-align: center;
            margin-bottom: 30px;
            max-width: 800px;
        }
        
        .demo-title {
            font-size: 1.8rem;
            color: var(--primary);
            margin-bottom: 15px;
        }
        
        .demo-description {
            font-size: 1.1rem;
            color: var(--dark);
            opacity: 0.9;
        }
        
        .memory-grid {
            display: grid;
            grid-template-columns: repeat(8, 1fr);
            gap: 15px;
            width: 100%;
            max-width: 800px;
            margin: 0 auto;
        }
        
        .memory-block {
            aspect-ratio: 1;
            background: #e0e7ff;
            border-radius: 8px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: 600;
            color: var(--dark);
            transition: all 0.3s ease;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }
        
        .memory-block::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.2);
            z-index: 1;
        }
        
        .memory-block.normal {
            background: linear-gradient(135deg, #e0e7ff, #d0e0ff);
            border: 2px solid var(--primary);
        }
        
        .memory-block.trap {
            background: linear-gradient(135deg, #4a6cfa, #7e68ff);
            border: 2px solid var(--secondary);
            color: white;
            animation: pulse-blue 2s infinite;
        }
        
        .memory-block.accessed {
            background: linear-gradient(135deg, #41d695, #2dcb84);
            border: 2px solid var(--success);
            color: white;
        }
        
        .memory-block.cheat-detected {
            background: linear-gradient(135deg, #ff6b6b, #ff5252);
            border: 2px solid var(--accent);
            color: white;
            animation: pulse-red 1s infinite;
        }
        
        @keyframes pulse-blue {
            0% { box-shadow: 0 0 0 0 rgba(74, 108, 250, 0.4); }
            70% { box-shadow: 0 0 0 10px rgba(74, 108, 250, 0); }
            100% { box-shadow: 0 0 0 0 rgba(74, 108, 250, 0); }
        }
        
        @keyframes pulse-red {
            0% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.4); }
            70% { box-shadow: 0 0 0 10px rgba(255, 107, 107, 0); }
            100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0); }
        }
        
        .memory-block .address {
            font-size: 0.9rem;
            z-index: 2;
        }
        
        .memory-block .status {
            position: absolute;
            bottom: 5px;
            font-size: 0.7rem;
            opacity: 0.8;
            z-index: 2;
        }
        
        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            justify-content: center;
            margin: 30px 0;
            width: 100%;
            max-width: 800px;
        }
        
        .btn {
            padding: 14px 26px;
            border-radius: 12px;
            border: none;
            font-weight: 600;
            cursor: pointer;
            transition: var(--transition);
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 1rem;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }
        
        .btn-primary {
            background: linear-gradient(to right, var(--primary), var(--secondary));
            color: white;
        }
        
        .btn-primary:hover {
            box-shadow: 0 7px 20px rgba(74, 108, 250, 0.4);
            transform: translateY(-3px);
        }
        
        .btn-secondary {
            background: #ffffff;
            color: var(--dark);
            border: 1px solid #e0e0e0;
        }
        
        .btn-secondary:hover {
            background: #f8f9ff;
            transform: translateY(-3px);
        }
        
        .btn-success {
            background: linear-gradient(to right, var(--success), #2dcb84);
            color: white;
        }
        
        .btn-warning {
            background: linear-gradient(to right, var(--warning), #ffb300);
            color: white;
        }
        
        .result-panel {
            background: white;
            border-radius: 16px;
            padding: 25px;
            margin: 30px auto;
            max-width: 800px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
            text-align: center;
            border-top: 5px solid var(--primary);
        }
        
        .result-title {
            font-size: 1.5rem;
            margin-bottom: 20px;
            color: var(--primary);
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
        }
        
        .result-content {
            font-size: 1.2rem;
            line-height: 1.6;
        }
        
        .result-success {
            color: var(--success);
            font-weight: 600;
        }
        
        .result-danger {
            color: var(--accent);
            font-weight: 600;
        }
        
        .explanation {
            background: #f8f9ff;
            border-radius: 16px;
            padding: 25px;
            margin: 30px auto;
            max-width: 800px;
        }
        
        .explanation-title {
            font-size: 1.3rem;
            color: var(--primary);
            margin-bottom: 15px;
        }
        
        .steps {
            display: flex;
            flex-direction: column;
            gap: 20px;
            margin-top: 25px;
        }
        
        .step {
            display: flex;
            align-items: flex-start;
            gap: 15px;
        }
        
        .step-number {
            min-width: 30px;
            height: 30px;
            border-radius: 50%;
            background: var(--primary);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            flex-shrink: 0;
            margin-top: 5px;
        }
        
        .step-content {
            flex: 1;
        }
        
        .code-block {
            background: linear-gradient(135deg, #2c3e50, #1a2530);
            color: #e1e1e1;
            border-radius: 12px;
            padding: 25px;
            font-family: 'Fira Code', monospace;
            margin: 25px 0;
            overflow: auto;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            position: relative;
        }
        
        .code-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }
        
        .code-title {
            color: var(--accent);
            font-weight: 600;
            font-size: 1.1rem;
        }
        
        .code-copy {
            background: rgba(255, 255, 255, 0.15);
            color: white;
            border: none;
            padding: 5px 15px;
            border-radius: 5px;
            cursor: pointer;
            transition: background 0.2s ease;
            font-family: inherit;
            font-size: 0.9rem;
        }
        
        .code-copy:hover {
            background: rgba(255, 255, 255, 0.25);
        }
        
        .code-copy:active {
            transform: scale(0.95);
        }
        
        footer {
            background: var(--dark);
            color: white;
            padding: 50px 0 30px;
            text-align: center;
            margin-top: 50px;
        }
        
        .footer-content {
            max-width: 800px;
            margin: 0 auto;
        }
        
        .social-icons {
            display: flex;
            justify-content: center;
            gap: 25px;
            margin: 30px 0;
        }
        
        .social-icon {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.1);
            color: white;
            font-size: 1.4rem;
            transition: var(--transition);
        }
        
        .social-icon:hover {
            background: var(--primary);
            transform: translateY(-5px);
        }
        
        /* Responsive Design */
        @media (max-width: 768px) {
            nav ul {
                gap: 10px;
                flex-wrap: wrap;
                justify-content: center;
            }
            
            .header-content {
                flex-direction: column;
                gap: 20px;
            }
            
            .section-header {
                padding: 20px;
            }
            
            .section-title {
                font-size: 1.5rem;
            }
            
            .memory-grid {
                grid-template-columns: repeat(4, 1fr);
            }
            
            .btn {
                width: 100%;
                justify-content: center;
            }
        }
    </style>
</head>
<body>
    <header>
        <div class="container">
            <div class="header-content">
                <div class="logo">
                    <div class="logo-icon">
                        <i class="fas fa-memory"></i>
                    </div>
                    <div class="logo-text">内存陷阱检测技术</div>
                </div>
                
                <nav>
                    <ul>
                        <li><a href="#intro" class="active"><i class="fas fa-home"></i> 简介</a></li>
                        <li><a href="#working"><i class="fas fa-cogs"></i> 工作原理</a></li>
                        <li><a href="#demo"><i class="fas fa-laptop-code"></i> 交互演示</a></li>
                        <li><a href="#code"><i class="fas fa-code"></i> 完整代码</a></li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>
    
    <div class="container">
        <main>
            <section id="intro" class="section">
                <div class="section-header">
                    <h2 class="section-title"><i class="fas fa-info-circle"></i> mincore函数与内存陷阱技术</h2>
                </div>
                <div class="section-content">
                    <div class="subsection">
                        <h3 class="subsection-title"><i class="fas fa-microscope"></i> 什么是mincore函数？</h3>
                        <p>mincore是一个UNIX/Linux系统调用，用于查询一段内存范围中哪些页面当前驻留在物理内存中（RAM中），而不是被交换到磁盘上。</p>
                        
                        <div class="code-block">
                            <div class="code-header">
                                <div class="code-title">mincore函数原型</div>
                                <button class="code-copy">复制代码</button>
                            </div>
                            <code>
#include &lt;unistd.h><br>
#include &lt;sys/mman.h><br><br>
int mincore(void *addr, size_t length, unsigned char *vec);
                            </code>
                        </div>
                        
                        <p>在反外挂系统中，mincore函数可以检测到异常的内存访问行为。游戏开发者会在关键数据结构周围设置"陷阱页"，这些页面在正常游戏流程中不会被访问。当外挂尝试读取这些区域时，会触发陷阱机制。</p>
                    </div>
                </div>
            </section>
            
            <section id="working" class="section">
                <div class="section-header">
                    <h2 class="section-title"><i class="fas fa-cogs"></i> mincore工作原理</h2>
                </div>
                <div class="section-content">
                    <div class="subsection">
                        <h3 class="subsection-title"><i class="fas fa-brain"></i> 内存陷阱机制</h3>
                        <p>反外挂系统通过设置内存陷阱来检测非法访问：</p>
                        
                        <div class="steps">
                            <div class="step">
                                <div class="step-number">1</div>
                                <div class="step-content">
                                    <h4>设置陷阱页</h4>
                                    <p>在关键游戏数据周围分配特殊内存页，这些页面在正常游戏流程中不会被访问。</p>
                                </div>
                            </div>
                            
                            <div class="step">
                                <div class="step-number">2</div>
                                <div class="step-content">
                                    <h4>初始状态</h4>
                                    <p>陷阱页初始设置为未映射状态，当被访问时会产生缺页异常。</p>
                                </div>
                            </div>
                            
                            <div class="step">
                                <div class="step-number">3</div>
                                <div class="step-content">
                                    <h4>外挂访问</h4>
                                    <p>当外挂尝试读取受保护的游戏数据时，会访问这些陷阱页。</p>
                                </div>
                            </div>
                            
                            <div class="step">
                                <div class="step-number">4</div>
                                <div class="step-content">
                                    <h4>检测机制</h4>
                                    <p>通过mincore定期检查陷阱页状态。如果发现未被游戏代码访问的陷阱页驻留在内存中，说明有外部工具访问了它们。</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            
            <section id="demo" class="section">
                <div class="section-header">
                    <h2 class="section-title"><i class="fas fa-laptop-code"></i> mincore交互演示</h2>
                </div>
                <div class="section-content">
                    <div class="demo-container">
                        <div class="demo-header">
                            <h3 class="demo-title">内存陷阱检测演示</h3>
                            <p class="demo-description">
                                在下方内存网格中，蓝色方块表示陷阱内存页。正常玩家不会访问这些区域，而外挂会尝试访问它们以获取游戏数据。
                                点击"设下陷阱"按钮开始，然后模拟玩家行为，最后使用mincore检测非法访问。
                            </p>
                        </div>
                        
                        <div class="memory-grid" id="memory-grid">
                            <!-- Memory blocks will be generated by JS -->
                        </div>
                        
                        <div class="controls">
                            <button id="set-trap-btn" class="btn btn-primary">
                                <i class="fas fa-bomb"></i> 设下陷阱
                            </button>
                            <button id="simulate-player-btn" class="btn btn-success">
                                <i class="fas fa-user"></i> 模拟正常玩家
                            </button>
                            <button id="simulate-cheat-btn" class="btn btn-warning">
                                <i class="fas fa-user-secret"></i> 模拟外挂玩家
                            </button>
                            <button id="detect-btn" class="btn btn-secondary">
                                <i class="fas fa-search"></i> mincore检测
                            </button>
                            <button id="reset-btn" class="btn">
                                <i class="fas fa-redo"></i> 重置演示
                            </button>
                        </div>
                        
                        <div class="result-panel" id="result-panel">
                            <div class="result-title">
                                <i class="fas fa-info-circle"></i>
                                <span>检测结果</span>
                            </div>
                            <div class="result-content">
                                点击上方按钮开始演示...
                            </div>
                        </div>
                        
                        <div class="explanation">
                            <h3 class="explanation-title">演示说明</h3>
                            <p>这个交互演示展示了mincore函数如何检测非法内存访问：</p>
                            <ul style="margin-left: 25px; margin-top: 15px;">
                                <li><strong>蓝色方块</strong> - 陷阱内存页，正常游戏不会访问的区域</li>
                                <li><strong>绿色方块</strong> - 被访问的内存页（正常游戏数据）</li>
                                <li><strong>红色方块</strong> - 被非法访问的陷阱页</li>
                            </ul>
                            <p style="margin-top: 15px;">
                                当您模拟外挂玩家时，会尝试访问陷阱页。mincore检测会识别这些访问并标记为违规行为。
                            </p>
                        </div>
                    </div>
                </div>
            </section>
            
            <section id="code" class="section">
                <div class="section-header">
                    <h2 class="section-title"><i class="fas fa-code"></i> 完整C语言实现</h2>
                </div>
                <div class="section-content">
                    <div class="subsection">
                        <h3 class="subsection-title"><i class="fas fa-terminal"></i> mincore反外挂完整实现</h3>
                        <p>以下是一个完整的C语言实现，展示如何使用mincore函数检测外挂：</p>
                        
                        <div class="code-block">
                            <div class="code-header">
                                <div class="code-title">mincore_anti_cheat.c</div>
                                <button class="code-copy">复制代码</button>
                            </div>
                            <code>
#include &lt;stdio.h><br>
#include &lt;stdlib.h><br>
#include &lt;unistd.h><br>
#include &lt;sys/mman.h><br>
#include &lt;string.h><br>
#include &lt;time.h><br>
<br>
#define PAGE_SIZE getpagesize()<br>
#define TRAP_PAGES 4<br>
#define DETECTION_INTERVAL 3 // seconds<br>
<br>
// 游戏数据结构<br>
typedef struct {<br>
&nbsp;&nbsp;int player_id;<br>
&nbsp;&nbsp;float position_x;<br>
&nbsp;&nbsp;float position_y;<br>
&nbsp;&nbsp;int health;<br>
&nbsp;&nbsp;int ammo;<br>
} PlayerData;<br>
<br>
// 陷阱页结构<br>
typedef struct {<br>
&nbsp;&nbsp;void* address;<br>
&nbsp;&nbsp;int is_accessed;<br>
} TrapPage;<br>
<br>
TrapPage trap_pages[TRAP_PAGES];<br>
<br>
// 初始化陷阱页<br>
void init_trap_pages() {<br>
&nbsp;&nbsp;for (int i = 0; i < TRAP_PAGES; i++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 分配内存页<br>
&nbsp;&nbsp;&nbsp;&nbsp;trap_pages[i].address = mmap(NULL, PAGE_SIZE, PROT_READ, <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (trap_pages[i].address == MAP_FAILED) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("mmap failed");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 取消映射，使页面不可访问<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (madvise(trap_pages[i].address, PAGE_SIZE, MADV_DONTNEED) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("madvise failed");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;trap_pages[i].is_accessed = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;printf("陷阱页 %d 设置在地址: %p\n", i, trap_pages[i].address);<br>
&nbsp;&nbsp;}<br>
}<br>
<br>
// 检测陷阱页访问<br>
void detect_trap_access() {<br>
&nbsp;&nbsp;for (int i = 0; i < TRAP_PAGES; i++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;unsigned char vec;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 使用mincore检查页面状态<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (mincore(trap_pages[i].address, PAGE_SIZE, &vec) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("mincore failed");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 检查最低有效位（页面是否在内存中）<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (vec & 1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!trap_pages[i].is_accessed) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\033[1;31m检测到非法访问! 陷阱页 %d (%p) 被访问\033[0m\n", <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i, trap_pages[i].address);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 标记为已访问并重置<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trap_pages[i].is_accessed = 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 重置陷阱页<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (madvise(trap_pages[i].address, PAGE_SIZE, MADV_DONTNEED) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("madvise reset failed");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trap_pages[i].is_accessed = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;}<br>
}<br>
<br>
// 模拟正常游戏操作<br>
void simulate_game_operation(PlayerData* player) {<br>
&nbsp;&nbsp;// 更新玩家位置<br>
&nbsp;&nbsp;player->position_x += 1.5f;<br>
&nbsp;&nbsp;player->position_y += 0.5f;<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 减少弹药<br>
&nbsp;&nbsp;player->ammo--;<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;printf("玩家 %d 位置: (%.1f, %.1f), 弹药: %d\n", <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;player->player_id, player->position_x, player->position_y, player->ammo);<br>
}<br>
<br>
// 模拟外挂访问<br>
void simulate_cheat_access() {<br>
&nbsp;&nbsp;// 随机访问一个陷阱页<br>
&nbsp;&nbsp;int trap_index = rand() % TRAP_PAGES;<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 尝试读取陷阱页内容<br>
&nbsp;&nbsp;printf("\033[1;33m外挂尝试访问陷阱页 %d (%p)\033[0m\n", <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trap_index, trap_pages[trap_index].address);<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 访问陷阱页（这将触发缺页异常）<br>
&nbsp;&nbsp;char value = *((char*)trap_pages[trap_index].address);<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 防止编译器优化掉访问<br>
&nbsp;&nbsp;if (value == 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 这个分支永远不会执行，但防止编译器优化<br>
&nbsp;&nbsp;&nbsp;&nbsp;printf("陷阱页值: %d\n", value);<br>
&nbsp;&nbsp;}<br>
}<br>
<br>
int main() {<br>
&nbsp;&nbsp;printf("=== 基于mincore的反外挂系统演示 ===\n");<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 初始化随机种子<br>
&nbsp;&nbsp;srand(time(NULL));<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 初始化陷阱页<br>
&nbsp;&nbsp;init_trap_pages();<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 创建玩家数据<br>
&nbsp;&nbsp;PlayerData player = {<br>
&nbsp;&nbsp;&nbsp;&nbsp;.player_id = 1001,<br>
&nbsp;&nbsp;&nbsp;&nbsp;.position_x = 0.0f,<br>
&nbsp;&nbsp;&nbsp;&nbsp;.position_y = 0.0f,<br>
&nbsp;&nbsp;&nbsp;&nbsp;.health = 100,<br>
&nbsp;&nbsp;&nbsp;&nbsp;.ammo = 30<br>
&nbsp;&nbsp;};<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 主循环<br>
&nbsp;&nbsp;int game_loop = 1;<br>
&nbsp;&nbsp;int cycle = 0;<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;while (game_loop) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;printf("\n--- 游戏循环 %d ---\n", cycle++);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 模拟游戏操作<br>
&nbsp;&nbsp;&nbsp;&nbsp;simulate_game_operation(&player);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 随机决定是否模拟外挂<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (rand() % 4 == 0) { // 25%几率触发外挂<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;simulate_cheat_access();<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 检测陷阱页访问<br>
&nbsp;&nbsp;&nbsp;&nbsp;detect_trap_access();<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 等待检测间隔<br>
&nbsp;&nbsp;&nbsp;&nbsp;sleep(DETECTION_INTERVAL);<br>
&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;// 简单的游戏结束条件<br>
&nbsp;&nbsp;&nbsp;&nbsp;if (cycle > 10) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;game_loop = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\n游戏结束!\n");<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;}<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;// 清理陷阱页<br>
&nbsp;&nbsp;for (int i = 0; i < TRAP_PAGES; i++) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;munmap(trap_pages[i].address, PAGE_SIZE);<br>
&nbsp;&nbsp;}<br>
&nbsp;&nbsp;<br>
&nbsp;&nbsp;return 0;<br>
}
                            </code>
                        </div>
                        
                        <div class="steps">
                            <div class="step">
                                <div class="step-number">1</div>
                                <div class="step-content">
                                    <h4>编译与运行</h4>
                                    <p>在Linux系统上使用以下命令编译和运行程序：</p>
                                    <div class="code-block" style="margin-top: 15px;">
                                        <code>
gcc mincore_anti_cheat.c -o anti_cheat<br>
./anti_cheat
                                        </code>
                                    </div>
                                </div>
                            </div>
                            
                            <div class="step">
                                <div class="step-number">2</div>
                                <div class="step-content">
                                    <h4>程序输出</h4>
                                    <p>程序将模拟游戏运行和外挂行为，当检测到非法访问时会显示红色警告信息：</p>
                                    <div class="code-block" style="margin-top: 15px;">
                                        <code>
检测到非法访问! 陷阱页 2 (0x7f8d5c000000) 被访问
                                        </code>
                                    </div>
                                </div>
                            </div>
                            
                            <div class="step">
                                <div class="step-number">3</div>
                                <div class="step-content">
                                    <h4>实现原理</h4>
                                    <p>程序使用mmap分配陷阱页，然后使用madvise(MADV_DONTNEED)将其标记为未映射。当外挂尝试访问这些页面时，系统会将其加载到内存。mincore检测到页面在内存中后，标记为非法访问。</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </main>
    </div>
    
    <footer>
        <div class="container">
            <div class="footer-content">
                <h3>恩佐-lidi</h3>
                <p>我心匪石不可转,我心匪席不可卷</p>
                
                <div class="social-icons">
                    <a href="#" class="social-icon"><i class="fab fa-github"></i></a>
                    <a href="#" class="social-icon"><i class="fab fa-twitter"></i></a>
                    <a href="#" class="social-icon"><i class="fab fa-linkedin-in"></i></a>
                    <a href="#" class="social-icon"><i class="fab fa-youtube"></i></a>
                </div>
                
                <p>&copy; 2025 mincore函数深度解析 · 保留所有权利</p>
            </div>
        </div>
    </footer>
    
    <script>
        // Initialize memory grid
        function initMemoryGrid() {
            const grid = document.getElementById('memory-grid');
            grid.innerHTML = '';
            
            const blockCount = 32;
            
            for (let i = 0; i < blockCount; i++) {
                const block = document.createElement('div');
                block.classList.add('memory-block', 'normal');
                block.dataset.address = `0x${(0x1000 + i * 0x400).toString(16).toUpperCase()}`;
                block.dataset.type = 'normal';
                block.dataset.accessed = 'false';
                
                const addressSpan = document.createElement('div');
                addressSpan.classList.add('address');
                addressSpan.textContent = block.dataset.address;
                
                const statusSpan = document.createElement('div');
                statusSpan.classList.add('status');
                statusSpan.textContent = '未访问';
                
                block.appendChild(addressSpan);
                block.appendChild(statusSpan);
                
                // Add click event for cheat simulation
                block.addEventListener('click', function() {
                    if (this.dataset.type === 'trap' && this.dataset.accessed === 'false') {
                        this.classList.remove('trap');
                        this.classList.add('cheat-detected');
                        this.querySelector('.status').textContent = '非法访问!';
                        this.dataset.accessed = 'true';
                    }
                });
                
                grid.appendChild(block);
            }
        }
        
        // Set traps randomly
        function setTraps() {
            const blocks = document.querySelectorAll('.memory-block');
            const trapCount = 6;
            const trapIndices = [];
            
            // Reset all blocks
            blocks.forEach(block => {
                block.classList.remove('trap', 'accessed', 'cheat-detected');
                block.classList.add('normal');
                block.dataset.type = 'normal';
                block.dataset.accessed = 'false';
                block.querySelector('.status').textContent = '未访问';
            });
            
            // Select random trap positions
            while (trapIndices.length < trapCount) {
                const randomIndex = Math.floor(Math.random() * blocks.length);
                if (!trapIndices.includes(randomIndex)) {
                    trapIndices.push(randomIndex);
                }
            }
            
            // Set traps
            trapIndices.forEach(index => {
                blocks[index].classList.remove('normal');
                blocks[index].classList.add('trap');
                blocks[index].dataset.type = 'trap';
                blocks[index].querySelector('.status').textContent = '陷阱页';
            });
            
            updateResultPanel('陷阱已设置！蓝色方块表示陷阱内存页。');
        }
        
        // Simulate normal player
        function simulateNormalPlayer() {
            const blocks = document.querySelectorAll('.memory-block:not(.trap)');
            const accessCount = 8;
            const accessedIndices = [];
            
            // Reset previous accesses (except traps)
            blocks.forEach(block => {
                if (block.dataset.type !== 'trap') {
                    block.classList.remove('accessed', 'cheat-detected');
                    block.classList.add('normal');
                    block.dataset.accessed = 'false';
                    block.querySelector('.status').textContent = '未访问';
                }
            });
            
            // Select random blocks to access
            while (accessedIndices.length < accessCount) {
                const randomIndex = Math.floor(Math.random() * blocks.length);
                if (!accessedIndices.includes(randomIndex) && blocks[randomIndex].dataset.type !== 'trap') {
                    accessedIndices.push(randomIndex);
                }
            }
            
            // Simulate access with animation
            accessedIndices.forEach((index, i) => {
                setTimeout(() => {
                    blocks[index].classList.remove('normal');
                    blocks[index].classList.add('accessed');
                    blocks[index].dataset.accessed = 'true';
                    blocks[index].querySelector('.status').textContent = '已访问';
                }, i * 300);
            });
            
            updateResultPanel('正常玩家行为模拟完成。绿色方块表示被访问的正常内存页。');
        }
        
        // Simulate cheat player
        function simulateCheatPlayer() {
            const blocks = document.querySelectorAll('.memory-block');
            const trapBlocks = document.querySelectorAll('.memory-block.trap');
            const normalBlocks = document.querySelectorAll('.memory-block:not(.trap)');
            
            // Reset previous accesses
            blocks.forEach(block => {
                if (block.dataset.type === 'trap' && block.dataset.accessed === 'true') {
                    block.classList.remove('cheat-detected');
                    block.classList.add('trap');
                    block.dataset.accessed = 'false';
                    block.querySelector('.status').textContent = '陷阱页';
                }
            });
            
            // Access some normal blocks (模拟外挂访问正常游戏数据)
            const normalAccessCount = Math.min(4, normalBlocks.length);
            for (let i = 0; i < normalAccessCount; i++) {
                const randomIndex = Math.floor(Math.random() * normalBlocks.length);
                setTimeout(() => {
                    normalBlocks[randomIndex].classList.remove('normal');
                    normalBlocks[randomIndex].classList.add('accessed');
                    normalBlocks[randomIndex].dataset.accessed = 'true';
                    normalBlocks[randomIndex].querySelector('.status').textContent = '已访问';
                }, i * 300);
            }
            
            // Access some traps (模拟外挂访问陷阱)
            trapBlocks.forEach((block, i) => {
                if (Math.random() > 0.3) { // 70% chance to access each trap
                    setTimeout(() => {
                        block.classList.remove('trap');
                        block.classList.add('cheat-detected');
                        block.querySelector('.status').textContent = '非法访问!';
                        block.dataset.accessed = 'true';
                    }, (normalAccessCount + i) * 500);
                }
            });
            
            updateResultPanel('外挂玩家行为模拟完成。红色方块表示被非法访问的陷阱页。');
        }
        
        // Run mincore detection
        function runDetection() {
            const trapBlocks = document.querySelectorAll('.memory-block.trap');
            const accessedTraps = document.querySelectorAll('.memory-block.cheat-detected');
            
            if (accessedTraps.length > 0) {
                // Cheat detected
                updateResultPanel(
                    '<span class="result-danger">发现违规用户！非法访问了陷阱内存</span>',
                    'result-danger'
                );
            } else {
                // No cheat detected
                updateResultPanel(
                    '<span class="result-success">您是尊贵的绿色玩家</span>',
                    'result-success'
                );
            }
        }
        
        // Update result panel
        function updateResultPanel(message, className = '') {
            const panel = document.getElementById('result-panel');
            panel.querySelector('.result-content').innerHTML = message;
            
            // Update icon based on message
            const icon = panel.querySelector('.result-title i');
            if (className === 'result-danger') {
                icon.className = 'fas fa-exclamation-triangle';
                panel.style.borderTopColor = 'var(--accent)';
            } else if (className === 'result-success') {
                icon.className = 'fas fa-check-circle';
                panel.style.borderTopColor = 'var(--success)';
            } else {
                icon.className = 'fas fa-info-circle';
                panel.style.borderTopColor = 'var(--primary)';
            }
        }
        
        // Initialize everything
        document.addEventListener('DOMContentLoaded', () => {
            initMemoryGrid();
            
            // Setup button events
            document.getElementById('set-trap-btn').addEventListener('click', setTraps);
            document.getElementById('simulate-player-btn').addEventListener('click', simulateNormalPlayer);
            document.getElementById('simulate-cheat-btn').addEventListener('click', simulateCheatPlayer);
            document.getElementById('detect-btn').addEventListener('click', runDetection);
            document.getElementById('reset-btn').addEventListener('click', () => {
                initMemoryGrid();
                updateResultPanel('演示已重置。点击"设下陷阱"按钮开始新的演示。');
            });
            
            // Copy code button functionality
            document.querySelectorAll('.code-copy').forEach(btn => {
                btn.addEventListener('click', () => {
                    const codeBlock = btn.closest('.code-block');
                    const code = codeBlock.querySelector('code').textContent;
                    
                    navigator.clipboard.writeText(code).then(() => {
                        const originalText = btn.textContent;
                        btn.innerHTML = '<i class="fas fa-check"></i> 已复制';
                        
                        setTimeout(() => {
                            btn.textContent = originalText;
                        }, 2000);
                    });
                });
            });
            
            // Navigation highlighting
            const sections = document.querySelectorAll('section');
            const navLinks = document.querySelectorAll('nav a');
            
            function setActiveLink() {
                let current = '';
                
                sections.forEach(section => {
                    const sectionTop = section.offsetTop;
                    const sectionHeight = section.clientHeight;
                    
                    if (pageYOffset >= sectionTop - 150) {
                        current = section.getAttribute('id');
                    }
                });
                
                navLinks.forEach(link => {
                    link.classList.remove('active');
                    if (link.getAttribute('href').substring(1) === current) {
                        link.classList.add('active');
                    }
                });
            }
            
            window.addEventListener('scroll', setActiveLink);
            setActiveLink(); // Initialize on load
        });
    </script>
</body>
</html>